﻿using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
using System;
using System.IO;
using System.Numerics;
using System.Text;
using UtilZ.Dotnet.Ex.FourierTransform;
using UtilZ.Dotnet.Ex.Model;

namespace ConAppCore.Test
{
    unsafe internal class TestFourierEx
    {
        public static void Test()
        {
            //注:测试的时候需要注意,数据点数分为奇数、偶数、小于1024和大于等于1024四种场景

            //int count = 100;
            int count = 2048;
            string filePath = @"D:\Projects\212\data\300_NarrowIQ_DDC0_512000_200000_B10000_P20000_E25000_Alg_W8A_VarBdFMFSK_3_20220302160758.dat";
            filePath = @"D:\Projects\212\data\152_NarrowIQ_DDC1_384000_150000_20220110154801_4fsk.dat";
            filePath = @"D:\Projects\212\data\IQ_120MHz_10KHz_50KHz_时间_2022-6-14_14-45-47_秒内时间398559340ns通道0_oqpsk.dat";
            filePath = @"D:\sigALL\QPSK\2_5M\20240618141817_IQ_AAAA041108ZD01_F_0500000000_B_0005000000_S_0006400000_ns_2744851981.wav";

            //TestForwardComplex32(count, filePath);
            //TestForwardComplex(count, filePath);
            //TestInverseComplex32(count, filePath);
            //TestInverseComplex(count, filePath);

            //ForwardCompare();
            TestForwardRealFloat(count, filePath);
            TestForwardRealDouble(count, filePath);

            TestInverseRealFloat(count, filePath);
            TestInverseRealDouble(count, filePath);

            //InverseCompare();
        }

        private static void TestInverseRealDouble(int count, string filePath)
        {
            var data1Arr = new double[count + 2];
            using var pointer = new UnmanagedMemoryPointer<double>(data1Arr.Length);
            var samples = pointer.GetSpanZ();

            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            for (int i = 0; i < data1Arr.Length; i++)
            {
                data1Arr[i] = reader.ReadInt16();
                samples[i] = data1Arr[i];
            }
            Fourier.InverseReal(data1Arr, count, FourierOptions.Matlab);

            using var tempPointer = new UnmanagedMemoryPointer<Complex>(count);
            var temp = tempPointer.GetSpanZ();
            FourierEx.InverseReal(samples, temp, FourierOptions.Matlab);


            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < data1Arr.Length; i++)
            {
                sb1.Append(data1Arr[i]);
                sb1.Append(',');

                sb2.Append(samples[i]);
                sb2.Append(',');
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }
        private static void TestInverseRealFloat(int count, string filePath)
        {
            var data1Arr = new float[count + 2];
            using var pointer = new UnmanagedMemoryPointer<float>(data1Arr.Length);
            var samples = pointer.GetSpanZ();

            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            for (int i = 0; i < data1Arr.Length; i++)
            {
                data1Arr[i] = reader.ReadInt16();
                samples[i] = data1Arr[i];
            }
            Fourier.InverseReal(data1Arr, count, FourierOptions.Matlab);

            using var tempPointer = new UnmanagedMemoryPointer<Complex32>(count);
            var temp = tempPointer.GetSpanZ();
            FourierEx.InverseReal(samples, temp, FourierOptions.Matlab);


            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < data1Arr.Length; i++)
            {
                sb1.Append(data1Arr[i]);
                sb1.Append(',');

                sb2.Append(samples[i]);
                sb2.Append(',');
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }


        private static void TestForwardRealDouble(int count, string filePath)
        {
            var data1Arr = new double[count + 2];
            using var pointer = new UnmanagedMemoryPointer<double>(data1Arr.Length);
            var samples = pointer.GetSpanZ();

            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            for (int i = 0; i < data1Arr.Length; i++)
            {
                data1Arr[i] = reader.ReadInt16();
                samples[i] = data1Arr[i];
            }
            Fourier.ForwardReal(data1Arr, count, FourierOptions.Matlab);

            using var tempPointer = new UnmanagedMemoryPointer<Complex>(count);
            var temp = tempPointer.GetSpanZ();
            FourierEx.ForwardReal(samples, temp, FourierOptions.Matlab);


            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < data1Arr.Length; i++)
            {
                sb1.Append(data1Arr[i]);
                sb1.Append(',');

                sb2.Append(samples[i]);
                sb2.Append(',');
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }
        private static void TestForwardRealFloat(int count, string filePath)
        {
            var data1Arr = new float[count + 2];
            using var pointer = new UnmanagedMemoryPointer<float>(data1Arr.Length);
            var samples = pointer.GetSpanZ();

            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            for (int i = 0; i < data1Arr.Length; i++)
            {
                data1Arr[i] = reader.ReadInt16();
                samples[i] = data1Arr[i];
            }
            Fourier.ForwardReal(data1Arr, count, FourierOptions.Matlab);

            using var tempPointer = new UnmanagedMemoryPointer<Complex32>(count);
            var temp = tempPointer.GetSpanZ();
            FourierEx.ForwardReal(samples, temp, FourierOptions.Matlab);


            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < data1Arr.Length; i++)
            {
                sb1.Append(data1Arr[i]);
                sb1.Append(',');

                sb2.Append(samples[i]);
                sb2.Append(',');
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }










        private static void InverseCompare()
        {
            string[] lineIArr = File.ReadAllLines(@"D:\Temp\iii.txt");
            string[] lineQArr = File.ReadAllLines(@"D:\Temp\qqq.txt");
            int length = lineIArr.Length;


            length = 100;
            length = 1999;
            length = 99;

            using var pointer = new UnmanagedMemoryPointer<Complex>(length);
            using var pointerIQ = new IQUnmanagedMemoryPointer<double>(length);

            SpanZ<Complex> span = pointer.GetSpanZ();
            Complex[] dataComplexClass1Arr = new Complex[length];
            IQSpanZ<double> samples = pointerIQ.GetIQSpanZ();

            //for (int i = 0; i < length; i++)
            //{
            //    span[i] = new Complex(i + 1, i + 1);
            //    dataComplexClass1Arr[i] = new Complex(i + 1, i + 1);
            //}
            for (int i = 0; i < length; i++)
            {
                samples.IDataPtr[i] = double.Parse(lineIArr[i]);
                samples.QDataPtr[i] = double.Parse(lineQArr[i]);

                span[i] = new Complex(double.Parse(lineIArr[i]), double.Parse(lineQArr[i]));
                dataComplexClass1Arr[i] = new Complex(double.Parse(lineIArr[i]), double.Parse(lineQArr[i]));
            }



            Fourier.Inverse(dataComplexClass1Arr, FourierOptions.Matlab);
            FourierEx.Inverse(span, FourierOptions.Matlab);
            FourierEx.Inverse(samples, FourierOptions.Matlab);

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            StringBuilder sb3 = new StringBuilder();
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(span[i].Real);
                sb2.Append(',');
                sb2.AppendLine(span[i].Imaginary.ToString());

                sb3.Append(samples.IDataPtr[i]);
                sb3.Append(',');
                sb3.AppendLine(samples.QDataPtr[i].ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();
            string str3 = sb3.ToString();

            if (string.Equals(str, str3))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }

        }

        private static void ForwardCompare()
        {
            string[] lineIArr = File.ReadAllLines(@"D:\Temp\iii.txt");
            string[] lineQArr = File.ReadAllLines(@"D:\Temp\qqq.txt");
            int length = lineIArr.Length;


            //length = 100;
            //length = 1999;

            using var pointer = new UnmanagedMemoryPointer<Complex>(length);
            using var pointerIQ = new IQUnmanagedMemoryPointer<double>(length);

            SpanZ<Complex> span = pointer.GetSpanZ();
            Complex[] dataComplexClass1Arr = new Complex[length];
            IQSpanZ<double> samples = pointerIQ.GetIQSpanZ();

            //for (int i = 0; i < length; i++)
            //{
            //    span[i] = new Complex(i + 1, i + 1);
            //    dataComplexClass1Arr[i] = new Complex(i + 1, i + 1);
            //}
            for (int i = 0; i < length; i++)
            {
                samples.IDataPtr[i] = double.Parse(lineIArr[i]);
                samples.QDataPtr[i] = double.Parse(lineQArr[i]);

                span[i] = new Complex(double.Parse(lineIArr[i]), double.Parse(lineQArr[i]));
                dataComplexClass1Arr[i] = new Complex(double.Parse(lineIArr[i]), double.Parse(lineQArr[i]));
            }



            Fourier.Forward(dataComplexClass1Arr, FourierOptions.Matlab);
            FourierEx.Forward(span, FourierOptions.Matlab);
            FourierEx.Forward(samples, FourierOptions.Matlab);

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            StringBuilder sb3 = new StringBuilder();
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(span[i].Real);
                sb2.Append(',');
                sb2.AppendLine(span[i].Imaginary.ToString());

                sb3.Append(samples.IDataPtr[i]);
                sb3.Append(',');
                sb3.AppendLine(samples.QDataPtr[i].ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();
            string str3 = sb3.ToString();

            if (string.Equals(str, str3))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }


        }





        private static void TestInverseComplex(int count, string filePath)
        {
            using var pointer = new UnmanagedMemoryPointer<Complex>();
            pointer.Check(count);

            Complex[] complexes = new Complex[count];
            SpanZ<Complex> dataComplexClass1Arr = new SpanZ<Complex>(pointer.DataPtr, count);
            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            short iData, qData;
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                iData = reader.ReadInt16();
                qData = reader.ReadInt16();
                dataComplexClass1Arr[i] = new Complex(iData, qData);

                complexes[i] = new Complex(iData, qData);
            }
            FourierEx.Inverse(dataComplexClass1Arr, FourierOptions.Matlab);
            Fourier.Inverse(complexes, FourierOptions.Matlab);

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(complexes[i].Real);
                sb2.Append(',');
                sb2.AppendLine(complexes[i].Imaginary.ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }

        private static void TestInverseComplex32(int count, string filePath)
        {
            using var pointer = new UnmanagedMemoryPointer<Complex32>(count);


            Complex32[] complexes = new Complex32[count];
            SpanZ<Complex32> dataComplexClass1Arr = new SpanZ<Complex32>(pointer.DataPtr, count);
            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            short iData, qData;
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                iData = reader.ReadInt16();
                qData = reader.ReadInt16();
                dataComplexClass1Arr[i] = new Complex32(iData, qData);

                complexes[i] = new Complex32(iData, qData);
            }
            FourierEx.Inverse(dataComplexClass1Arr, FourierOptions.Matlab);
            Fourier.Inverse(complexes, FourierOptions.Matlab);

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(complexes[i].Real);
                sb2.Append(',');
                sb2.AppendLine(complexes[i].Imaginary.ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }


        private static void TestForwardComplex(int count, string filePath)
        {
            using var pointer = new UnmanagedMemoryPointer<Complex>(count);
            Complex[] complexes = new Complex[count];

            SpanZ<Complex> dataComplexClass1Arr = new SpanZ<Complex>(pointer.DataPtr, count);
            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            short iData, qData;
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                iData = reader.ReadInt16();
                qData = reader.ReadInt16();
                dataComplexClass1Arr[i] = new Complex(iData, qData);

                complexes[i] = new Complex(iData, qData);
            }
            FourierEx.Forward(dataComplexClass1Arr, FourierOptions.Matlab);

            Fourier.Forward(complexes, FourierOptions.Matlab);


            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(complexes[i].Real);
                sb2.Append(',');
                sb2.AppendLine(complexes[i].Imaginary.ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }
        }

        private static void TestForwardComplex32(int count, string filePath)
        {
            using var pointer = new UnmanagedMemoryPointer<Complex32>(count);
            using var pointerIQ = new IQUnmanagedMemoryPointer<int>(count);
            Complex32[] complexes = new Complex32[count];
            SpanZ<Complex32> dataComplexClass1Arr = new SpanZ<Complex32>(pointer.DataPtr, count);
            IQSpanZ<int> spanZ = pointerIQ.GetIQSpanZ();

            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var reader = new BinaryReader(fileStream);
            short iData, qData;
            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                iData = reader.ReadInt16();
                qData = reader.ReadInt16();
                dataComplexClass1Arr[i] = new Complex32(iData, qData);

                complexes[i] = new Complex32(iData, qData);

                spanZ.IDataPtr[i] = iData;
                spanZ.QDataPtr[i] = qData;
            }
            FourierEx.Forward(dataComplexClass1Arr, FourierOptions.Matlab);
            Fourier.Forward(complexes, FourierOptions.Matlab);
            //FourierEx.Forward(spanZ, FourierOptions.Matlab);

            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            StringBuilder sb3 = new StringBuilder();

            for (int i = 0; i < dataComplexClass1Arr.Length; i++)
            {
                sb1.Append(dataComplexClass1Arr[i].Real);
                sb1.Append(',');
                sb1.AppendLine(dataComplexClass1Arr[i].Imaginary.ToString());

                sb2.Append(complexes[i].Real);
                sb2.Append(',');
                sb2.AppendLine(complexes[i].Imaginary.ToString());

                sb3.Append(spanZ.IDataPtr[i]);
                sb3.Append(',');
                sb3.AppendLine(spanZ.QDataPtr[i].ToString());
            }
            string str = sb1.ToString();
            string strSrc = sb2.ToString();
            string str3 = sb3.ToString();

            if (string.Equals(str, strSrc))
            {
                Console.WriteLine("ok");
            }
            else
            {
                Console.WriteLine("不同");
            }

            //if (string.Equals(str, str3))
            //{
            //    Console.WriteLine("ok");
            //}
            //else
            //{
            //    Console.WriteLine("不同");
            //}
        }
    }
}
